<?php

namespace app\admin\logic;

use app\admin\model\Company;
use app\admin\model\Goods;
use app\admin\model\GoodsSpec;
use app\enum\GoodsUnitType;
use app\enum\IntoOrderRelatedType;
use app\enum\OutOrderRelatedType;
use app\enum\IntoOrderStatus;
use app\enum\OrderPaymentType;
use app\enum\OrderSignPaymentType;
use app\enum\OrderType;
use app\enum\OutOrderStatus;
use app\enum\WarehouseAccountableType;
use support\Cache;
use think\facade\Db;

/**
 * 经销商逻辑层
 */
class StatisticsLogic extends BaseLogic
{

    /**
     * 获取货值列表
     * @return array
     */
    public function getCargoList($params = [], $page = 1, $limit = 20): array
    {
        $list = [];

        $initStock = $this->initStock();
        $stockTypes = [];
        foreach (GoodsUnitType::toSelect() as $item) {
            $stockTypes[] = 'type_' . $item['value'];
        }

        $dealerLogic = new DealerLogic();
        $dealerList = $dealerLogic->where(function ($query) use ($params) {
            if (!empty($params['dealer_id'])) {
                $query->where('id', $params['dealer_id']);
            }
            $companyIds = Company::where('is_internal', 0)->column('id');
            if (!empty($params['company_id'])) {
                $companyIds = array_intersect($companyIds, [$params['company_id']]);
            }
            $query->whereIn('company_id', $companyIds);
        })->field('id, name')->order('id asc');

        $dataList = $dealerList->paginate(['list_rows' => $limit, 'page' => $page])->each(function ($dealer) use (&$list, $initStock, $stockTypes) {
            $initData = array_merge($dealer->toArray(), [
                'total_stock' => $initStock,
                'total_amount' => 0,
            ]);
            foreach ($stockTypes as $typeKey) {
                $initData[$typeKey . '_stock'] = $initStock;
                $initData[$typeKey . '_amount'] = 0;
            }
            $list[$dealer['id']] = $initData;
        });

        //当前分页的经销商id
        $thisPageDealerIds = array_keys($list);

        $total = [
            'name' => '合计',
            'total_stock' => $initStock,
            'total_amount' => 0,
        ];

        foreach ($stockTypes as $typeKey) {
            $total[$typeKey . '_stock'] = $initStock;
            $total[$typeKey . '_amount'] = 0;
        }

        $warehouseWhere = [];
        if (!empty($companyId)) {
            $warehouseWhere[] = ['company_id', '=', $companyId];
        }
        $warehouseLogic = new WarehouseLogic();
        $warehouseIds = $warehouseLogic->where($warehouseWhere)->where('warehouse_type', WarehouseAccountableType::FIXED->value)->column('id');

        $goodsModel = new Goods();
        $goodsModel->whereIn('dealer_id', $dealerList->column('id'))->with([
            'batches' => function ($query) use ($warehouseIds) {
                $query->whereIn('warehouse_id', $warehouseIds)->where('quantity > 0')->field('goods_id, spec_id, attribute_type, quantity, sign_amount, initial_quantity');
            },
            'spec' => function ($query) {
                $query->field('goods_id, unit_name, unit_type, conversion_rate, agree_price');
            }
        ])->field('id, goods_name, dealer_id')->chunk(100, function ($goodsList) use (&$list, $initStock, $stockTypes, &$total, $thisPageDealerIds) {
            $goodsList = $goodsList->toArray();
            foreach ($goodsList as $goods) {
                if (!empty($goods['batches'])) {
                    // 获取可用单位
                    $unit = [];
                    if (!empty($goods['spec'])) {
                        foreach ($goods['spec'] as $spec) {
                            if (!isset($unit[$spec['unit_type']])) {
                                $unit[$spec['unit_type']] = [
                                    'unit' => $spec['unit_name'],
                                    'rate' => $spec['conversion_rate'],
                                    'agree_price' => $spec['agree_price'],
                                ];
                            }
                        }
                    }
                    krsort($unit);

                    // 处理商品多批次
                    foreach ($goods['batches'] as $batch) {
                        $stock = [];
                        foreach ($unit as $type => $unitInfo) {
                            $_stock = 0;
                            if ($unitInfo['rate'] > 1) {
                                $_stock = intdiv($batch['quantity'] ?? 0, $unitInfo['rate']);
                            } else {
                                $_stock = $batch['quantity'];
                            }
                            $batch['quantity'] -= $_stock * $unitInfo['rate'];
                            $stock['unit_' . $type]['stock'] = $_stock;
                            $stock['unit_' . $type]['amount'] = bcmul($_stock, $unitInfo['agree_price'], 2);
                        }

                        // 累加总库存与货值
                        foreach ($initStock as $key => $_) {
                            $total['total_stock'][$key] = bcadd(
                                $total['total_stock'][$key] ?? 0,
                                $stock[$key]['stock'] ?? 0
                            );
                            if (in_array($goods['dealer_id'], $thisPageDealerIds)) {
                                $list[$goods['dealer_id']]['total_stock'][$key] = bcadd(
                                    $list[$goods['dealer_id']]['total_stock'][$key] ?? 0,
                                    $stock[$key]['stock'] ?? 0,
                                    0
                                );
                            }
                        }
                        $totalAmount = array_reduce($stock, fn($carry, $s) => bcadd($carry, $s['amount'], 2), '0');
                        // 过期商品不计入总货值
                        if ($batch['attribute_type'] != 2) {
                            $total['total_amount'] = bcadd(
                                $total['total_amount'] ?? 0,
                                $totalAmount,
                                2
                            );
                            if (in_array($goods['dealer_id'], $thisPageDealerIds)) {
                                $list[$goods['dealer_id']]['total_amount'] = bcadd(
                                    $list[$goods['dealer_id']]['total_amount'] ?? 0,
                                    $totalAmount,
                                    2
                                );
                            }
                        }

                        // 动态累加分类库存与货值
                        $typeKey = 'type_' . $batch['attribute_type'];
                        if (in_array($typeKey, $stockTypes)) {
                            foreach ($initStock as $key => $_) {
                                $total[$typeKey . '_stock'][$key] = bcadd(
                                    $total[$typeKey . '_stock'][$key] ?? 0,
                                    $stock[$key]['stock'] ?? 0,
                                    0
                                );
                                if (in_array($goods['dealer_id'], $thisPageDealerIds)) {
                                    $list[$goods['dealer_id']][$typeKey . '_stock'][$key] = bcadd(
                                        $list[$goods['dealer_id']][$typeKey . '_stock'][$key] ?? 0,
                                        $stock[$key]['stock'] ?? 0,
                                        0
                                    );
                                }
                            }
                            $total[$typeKey . '_amount'] = bcadd(
                                $total[$typeKey . '_amount'] ?? 0,
                                $totalAmount,
                                2
                            );
                            if (in_array($goods['dealer_id'], $thisPageDealerIds)) {
                                $list[$goods['dealer_id']][$typeKey . '_amount'] = bcadd(
                                    $list[$goods['dealer_id']][$typeKey . '_amount'] ?? 0,
                                    $totalAmount,
                                    2
                                );
                            }
                        }
                    }
                }
            }
        });

        // 格式化单位显示
        $unitLabels = [];
        foreach (GoodsUnitType::toSelect() as $unit) {
            $unitLabels['unit_' . $unit['value']] = $unit['label'];
        }

        $stockTypes[] = 'total';
        foreach ($stockTypes as $typeKey) {
            $total[$typeKey . '_stock'] = $this->formatStockString($total[$typeKey . '_stock'], $unitLabels, $initStock);
        }

        $list = array_map(function ($item) use ($initStock, $unitLabels, $stockTypes) {
            // 格式化各 type_x 库存
            foreach ($stockTypes as $typeKey) {
                $item[$typeKey . '_stock'] = $this->formatStockString($item[$typeKey . '_stock'], $unitLabels, $initStock);
            }
            return $item;
        }, $list);

        $dataList = $dataList->toArray();
        $dataList['data'] = array_values($list);
        $dataList['summary'] = $total;

        return $dataList;
    }

    /**
     * 初始化每个单位的库存数据
     * @return array
     */
    private function initStock(): array
    {
        $unit = [];
        $unitEnum = array_column(GoodsUnitType::toSelect(), 'value');
        foreach ($unitEnum as $_unit) {
            $unit['unit_' . $_unit] = 0;
        }
        return array_reverse($unit);
    }

    /**
     * 格式化库存字符串（如：10整5中3散）
     * @param array $stockData
     * @param array $unitLabels
     * @param array $initStock
     * @return string
     */
    private function formatStockString(array $stockData, array $unitLabels, array $initStock): string
    {
        $result = '';
        foreach ($initStock as $key => $_) {
            $value = $stockData[$key] ?? 0;
            $label = $unitLabels[$key] ?? '';
            $result .= $value . $label;
        }
        return $result;
    }

    public function getInventoryList($params = [], $page = 1, $limit = 20): array
    {
        if (!empty($params['create_time'][0])) {
            $params['create_time'] = parseDateRange($params['create_time']);
        } else {
            unset($params['create_time']);
        }

        $list = [];
        $initStock = $this->initStock();

        $dealerLogic = new DealerLogic();
        $dealerList = $dealerLogic->where(function ($query) use ($params) {
            if (!empty($params['dealer_id'])) {
                $query->where('id', $params['dealer_id']);
            }
            $companyIds = Company::where('is_internal', 0)->column('id');
            if (!empty($params['company_id'])) {
                $companyIds = array_intersect($companyIds, [$params['company_id']]);
            }
            $query->whereIn('company_id', $companyIds);
        })->field('id, name')->order('id asc');

        $dataList = $dealerList->paginate(['list_rows' => $limit, 'page' => $page])->each(function ($dealer) use (&$list, $initStock) {
            $list[$dealer['id']] = [
                'id' => $dealer['id'],
                'name' => $dealer['name'],
                'into_stock' => $initStock,
                'into_amount' => 0,
                'out_stock' => $initStock,
                'out_amount' => 0,
            ];
        });

        //当前分页的经销商id
        $thisPageDealerIds = array_keys($list);

        $total = [
            'name' => '合计',
            'into_stock' => $this->initStock(),
            'into_amount' => 0,
            'out_stock' => $this->initStock(),
            'out_amount' => 0,
        ];

        $dealerIds = $dealerList->column('id');
        //查询符合条件的入库单
        //into_status = 2
        $intoOrderRes = Db::table('vk_into_order_statistics')
            ->whereIn('dealer_id', $dealerIds)
            ->where('into_status', IntoOrderStatus::FINISH->value)
            ->when(!empty($params['create_time']), function ($query) use ($params) {
                $query->where('update_time', 'between', $params['create_time']);
            })
            ->cursor();

        foreach ($intoOrderRes as $intoOrder) {
            if (empty($intoOrder['unit_type'])) {
                continue;
            }
            $total['into_stock']['unit_' . $intoOrder['unit_type']] += $intoOrder['num'];
            $total['into_amount'] = bcadd($total['into_amount'], $intoOrder['agree_total_price'] ?? 0, 2);

            if (in_array($intoOrder['dealer_id'], $thisPageDealerIds)) {
                $list[$intoOrder['dealer_id']]['into_stock']['unit_' . $intoOrder['unit_type']] += $intoOrder['num'] ?? 0;
                $list[$intoOrder['dealer_id']]['into_amount'] = bcadd($list[$intoOrder['dealer_id']]['into_amount'], $intoOrder['agree_total_price'] ?? 0, 2);
            }
        }
        
        $outOrderRes = Db::table('vk_out_order_statistics')
            ->whereIn('dealer_id', $dealerIds)
            ->where('status', OutOrderStatus::SIGN->value)
            ->when(!empty($params['create_time']), function ($query) use ($params) {
                $query->where('update_time', 'between', $params['create_time']);
            })
            ->order('id desc')->cursor();
            
        foreach($outOrderRes as $outOrder) {
            if (empty($outOrder['unit_type'])) {
                continue;
            }
            if (isset($total['out_stock']['unit_'. $outOrder['unit_type']])) {
                $total_agree_price = $outOrder['agree_total_price'] ?? 0;
                $total['out_stock']['unit_'. $outOrder['unit_type']] += $outOrder['num'] ?? 0;
                $total['out_amount'] = bcadd($total['out_amount'], $total_agree_price, 2);
                if (in_array($outOrder['dealer_id'], $thisPageDealerIds)) {
                    $list[$outOrder['dealer_id']]['out_stock']['unit_'. $outOrder['unit_type']] += $outOrder['num'] ?? 0;
                    $list[$outOrder['dealer_id']]['out_amount'] = bcadd($list[$outOrder['dealer_id']]['out_amount'], $total_agree_price, 2);
                }
            }
        }


        // 格式化单位显示
        $unitLabels = [];
        foreach (GoodsUnitType::toSelect() as $unit) {
            $unitLabels['unit_' . $unit['value']] = $unit['label'];
        }
        foreach (['into', 'out'] as $typeKey) {
            $total[$typeKey . '_stock'] = $this->formatStockString($total[$typeKey . '_stock'], $unitLabels, $initStock);
        }
        $list = array_map(function ($item) use ($initStock, $unitLabels) {
            // 格式化总库存
            foreach (['into', 'out'] as $typeKey) {
                $item[$typeKey . '_stock'] = $this->formatStockString($item[$typeKey . '_stock'], $unitLabels, $initStock);
            }
            return $item;
        }, $list);
        $dataList = $dataList->toArray();
        $dataList['data'] = array_values($list);
        $dataList['summary'] = $total;
        return $dataList;
    }


    /**
     * 经验业绩报表
     */
    public function getPerformanceList($params = [], $page = 1, $limit = 20): array
    {
        if (!empty($params['create_time'][0])) {
            $params['create_time'] = parseDateRange($params['create_time']);
        } else {
            unset($params['create_time']);
        }

        $list = [];

        $dealerLogic = new DealerLogic();
        $dealerList = $dealerLogic->where(function ($query) use ($params) {
            if (!empty($params['dealer_id'])) {
                $query->where('id', $params['dealer_id']);
            }
            $companyIds = Company::where('is_internal', 0)->column('id');
            if (!empty($params['company_id'])) {
                $companyIds = array_intersect($companyIds, [$params['company_id']]);
            }
            $query->whereIn('company_id', $companyIds);
        })->field('id, name')->order('id asc');

        $dataList = $dealerList->paginate(['list_rows' => $limit, 'page' => $page])->each(function ($dealer) use (&$list) {
            $list[$dealer['id']] = [
                'id' => $dealer['id'],
                'name' => $dealer['name'],
                'sign_amount' => 0, // 实收金额
                'receivable_amount' => 0,   // 应收金额
                'sales_amount' => 0,    // 销售金额
                'sales_order_num' => 0, // 销售单数
                'refund_amount' => 0, // 退款金额
                'refund_order_num' => 0,
                'pre_pay_amount' => 0, // 预付款金额
                'period_amount' => 0, // 账期金额
                'cash_amount' => 0, // 现金金额
                'company_amount' => 0, // 对公金额
            ];
        });

        //当前分页的经销商id
        $thisPageDealerIds = array_keys($list);

        $total = [
            'name' => '总计',
            'sign_amount' => 0,
            'receivable_amount' => 0,
            'sales_amount' => 0,
            'sales_order_num' => 0,
            'refund_amount' => 0,
            'refund_order_num' => 0,
            'pre_pay_amount' => 0,
            'period_amount' => 0,
            'cash_amount' => 0,
            'company_amount' => 0,
        ];

        $orderSignLogic = new OrderSignLogic();
        $orderSignLogic->whereIn('dealer_id', $thisPageDealerIds)
            ->when(!empty($params['create_time']), function ($query) use ($params) {
                $query->where('create_time', 'between', $params['create_time']);
            })->with(['salesOrder'])->order('id desc')
            ->chunk(100, function ($orderSignList) use (&$list, &$total, $thisPageDealerIds) {
                foreach ($orderSignList as $orderSign) {
                    if (!$orderSign->salesOrder || !$orderSign->salesOrder->detail) {
                        return;
                    }
                    // 销售单
                    if ($orderSign->salesOrder->order_type == OrderType::SALE->value) {
                        $total['sign_amount'] = bcadd($total['sign_amount'], $orderSign->sign_amount, 2);
                        $total['receivable_amount'] = bcadd($total['receivable_amount'], $orderSign->receivable_amount, 2);
                        $total['sales_order_num']++;

                        $detail = $orderSign->salesOrder->detail->toArray();
                        $salesAmount = array_sum(array_column($detail, 'total_price'));

                        $total['sales_amount'] = bcadd($total['sales_amount'], $salesAmount, 2);

                        if ($orderSign->payment_type  == OrderPaymentType::PAYMENT_TYPE_PREPAYMENT->value) {
                            $total['pre_pay_amount'] = bcadd($total['pre_pay_amount'], $orderSign->sign_amount, 2);
                        } elseif ($orderSign->payment_type  == OrderPaymentType::PAYMENT_TYPE_CREDIT->value) {
                            $total['period_amount'] = bcadd($total['period_amount'], $orderSign->sign_amount, 2);
                        } elseif ($orderSign->payment_type  == OrderPaymentType::PAYMENT_TYPE_CASH->value) {
                            $total['cash_amount'] = bcadd($total['cash_amount'], $orderSign->sign_amount, 2);
                        }

                        if ($orderSign->payment_model  == OrderSignPaymentType::PAYMENT_MODEL_COMPANY->value) {
                            $total['company_amount'] = bcadd($total['company_amount'], $orderSign->sign_amount, 2);
                        }

                        if (in_array($orderSign->dealer_id, $thisPageDealerIds)) {
                            // 实收金额
                            $list[$orderSign->dealer_id]['sign_amount'] = bcadd($list[$orderSign->dealer_id]['sign_amount'], $orderSign->sign_amount, 2);
                            // 应收金额
                            $list[$orderSign->dealer_id]['receivable_amount'] = bcadd($list[$orderSign->dealer_id]['receivable_amount'], $orderSign->receivable_amount, 2);
                            // 销售订单数量
                            $list[$orderSign->dealer_id]['sales_order_num']++;
                            // 销售金额
                            $list[$orderSign->dealer_id]['sales_amount'] = bcadd($list[$orderSign->dealer_id]['sales_amount'], $salesAmount, 2);
                            // 预付款
                            if ($orderSign->payment_type  == OrderPaymentType::PAYMENT_TYPE_PREPAYMENT->value) {
                                $list[$orderSign->dealer_id]['pre_pay_amount'] = bcadd($list[$orderSign->dealer_id]['pre_pay_amount'], $orderSign->sign_amount, 2);
                            }
                            // 账期
                            elseif ($orderSign->payment_type  == OrderPaymentType::PAYMENT_TYPE_CREDIT->value) {
                                $list[$orderSign->dealer_id]['period_amount'] = bcadd($list[$orderSign->dealer_id]['period_amount'], $orderSign->sign_amount, 2);
                            }
                            // 现金
                            elseif ($orderSign->payment_type  == OrderPaymentType::PAYMENT_TYPE_CASH->value) {
                                $list[$orderSign->dealer_id]['cash_amount'] = bcadd($list[$orderSign->dealer_id]['cash_amount'], $orderSign->sign_amount, 2);
                            }
                            // 对公
                            if ($orderSign->payment_model  == OrderSignPaymentType::PAYMENT_MODEL_COMPANY->value) {
                                $list[$orderSign->dealer_id]['company_amount'] = bcadd($list[$orderSign->dealer_id]['company_amount'], $orderSign->sign_amount, 2);
                            }
                        }
                    }
                    // 退货单
                    elseif ($orderSign->salesOrder->order_type == OrderType::RETURN_GOODS->value) {
                        $total['refund_amount'] = bcadd($total['refund_amount'], $orderSign->sign_amount, 2);
                        $total['refund_order_num']++;
                        if (in_array($orderSign->dealer_id, $thisPageDealerIds)) {
                            $list[$orderSign->dealer_id]['refund_amount'] = bcadd($list[$orderSign->dealer_id]['refund_amount'], $orderSign->sign_amount, 2);
                            $list[$orderSign->dealer_id]['refund_order_num']++;
                        }
                    }
                }
            });

        $dataList = $dataList->toArray();
        $dataList['data'] = array_values($list);
        $dataList['summary'] = $total;

        return $dataList;
    }

    /**
     * 业务数据报表
     */
    public function getBusinessDataList($params = [], $page = 1, $limit = 20): array
    {
        if (!empty($params['create_time'][0])) {
            $params['create_time'] = parseDateRange($params['create_time'], ',', true, 'Y-m-d');
        } else {
            unset($params['create_time']);
        }

        $where = [];
        if (!empty($params['company_id'])) {
            $where[] = ['company_id', '=', $params['company_id']];
        } else {
            $companyIds = Company::where('is_internal', 0)->column('id');
            $where[] = ['company_id', 'in', $companyIds];
        }
        if (!empty($params['create_time'])) {
            $where[] = ['stat_date', 'between', $params['create_time']];
        }

        $dealerStatLogic = new DealerStatisticsLogic();
        $list = $dealerStatLogic->getDailyCompanySummary($where, $page, $limit);

        return $list;
    }

    /**
     * 业务详情
     */
    public function getBusinessDetail($params = [], $page = 1, $limit = 20): array
    {
        $dealerStatLogic = new DealerStatisticsLogic();
        $list = $dealerStatLogic->getDealersByCompany($params, $page, $limit);
        return $list;
    }

    /**
     * 保存业务详情
     */
    public function saveBusinessDetail($data = []): bool
    {
        if (empty($data) || !is_array($data)) {
            return false;
        }
        $ids = array_column($data, 'id');
        if (empty($ids)) {
            return false;
        }
        $dealerStatLogic = new DealerStatisticsLogic();
        $existingIds = $dealerStatLogic->whereIn('id', $ids)->column('id');

        try {
            $dealerStatLogic->transaction(function () use ($dealerStatLogic, $data, $existingIds) {
                foreach ($data as $item) {
                    if (in_array($item['id'], $existingIds)) {
                        $dealerStatLogic->where('id', $item['id'])->update($item);
                    }
                }
            });
        } catch (\Exception $e) {
            return false;
        }
        return true;
    }
}
